package apobates.gui.formatter.service;

import apobates.gui.formatter.packet.JsonResult;
import apobates.gui.formatter.packet.ResourceType;
import apobates.gui.formatter.reader.RemoteForm;
import javafx.application.Platform;
import javafx.beans.binding.BooleanBinding;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.concurrent.WorkerStateEvent;
import org.reactfx.Change;
import org.reactfx.EventStream;
import org.reactfx.EventStreams;
import java.util.function.Consumer;

/**
 * 远程资源获取表单的执行服务
 */
public class RemoteFormLoaderService {
    private RemoteForm remoteForm;
    // 成功的标志为: isLoaded=true && isPaused=false
    // 是否加载结束
    private SimpleBooleanProperty loaded = new SimpleBooleanProperty(false);
    // 是否加载成功
    private SimpleBooleanProperty successed = new SimpleBooleanProperty(false);
    private Consumer<Boolean> fallbackFun = (status)-> System.out.println("[RFLS]default fallback function print:"+ status);

    public RemoteFormLoaderService(RemoteForm remoteForm) {
        this.remoteForm = remoteForm;
    }
    public void setCallbackFun(Consumer<Boolean> fallbackFun){
        this.fallbackFun = fallbackFun;
    }

    /**
     * 执行加载
     * @param recentLoadingFun 最近记录加载状态消费函数
     */
    public void load(Consumer<Boolean> recentLoadingFun){
        System.out.println("[RFLS]start execute Load --->");
        // 一开始加载重置状态值
        this.resetLoadStatus(recentLoadingFun);
        System.out.println("[RFLS]RemoteForm Load begin --->");
        // 执行加载
        final String resourcePath = remoteForm.getFilePath();
        System.out.println("[RFLS]RemoteForm Load path --->"+resourcePath);
        final String reqCharset = remoteForm.getFileEncoding();
        final int reqTime = remoteForm.getTimeout();
        // 若是URL
        if(remoteForm.getType() == ResourceType.URL && null!=resourcePath && !resourcePath.isEmpty() && resourcePath.startsWith("http")){
            System.out.println("[RFLS]http request config: timeout:"+reqTime+", charset:"+reqCharset);
            this.loadURLJsonResponse();
        }
        // 若是文件
        if(remoteForm.getType() == ResourceType.FILE && null!=resourcePath && !resourcePath.isEmpty()){
            System.out.println("[RFLS]filesystem request config: timeout:"+reqTime+", charset:"+reqCharset);
            this.loadFileJsonResponse();
        }
    }

    /**
     * 重置最近记录加载相关状态
     * @param recentLoadingFun 最近记录加载状态消费函数
     */
    private void resetLoadStatus(Consumer<Boolean> recentLoadingFun){
        System.out.println("[RFLS][RLS]set restart status attribute");
        this.loaded.set(false); // = false;
        this.successed.set(false); // = false;
        // 20230508@开启loading...
        if(null != recentLoadingFun){
            System.out.println("[RFLS][LOADED] loaded consume function start::False");
            // false开始
            // true结束
            recentLoadingFun.accept(false);
        }
    }
    private void finishLoadStatus(){
        System.out.println("[RFLS][FLS]set finish status--->");
        this.loaded.set(true); // = true;
        this.successed.set(true); // = true;
        //
        this.fallbackFun.accept(true);
    }
    private void failLoadStatus(){
        System.out.println("[RFLS][FLS]set fail status--->");
        this.loaded.set(true); // = true;
        this.successed.set(false); // = false;
        //
        this.fallbackFun.accept(false);
    }
    private void loadURLJsonResponse(){
        System.out.println("[RFLS]load json url:"+remoteForm.getFilePath()+", charset:"+remoteForm.getFileEncoding());
        // 异步
        RemoteJsonService service = new RemoteJsonService();
        service.setRemoteForm(remoteForm);
        service.setOnSucceeded((WorkerStateEvent t)-> {
            String leftTxStr = t.getSource().getValue().toString();
            // 填充到:rootLayout的leftSource
            this.fillRootLayoutLeftContent(leftTxStr, ResourceType.URL);
        });
        service.setOnFailed((WorkerStateEvent t)-> {
            System.out.println("[RFLS]load json url:"+remoteForm.getFilePath()+", happed fail(:)");
            this.fillRootLayoutLeftContent(null, ResourceType.URL);
        });
        service.start();
    }
    private void loadFileJsonResponse(){
        System.out.println("[RFLS]load json path:"+remoteForm.getFilePath()+", charset:"+remoteForm.getFileEncoding());
        // 异步
        JsonFileService service = new JsonFileService();
        service.setRemoteForm(remoteForm);
        service.setOnSucceeded((WorkerStateEvent t)-> {
            String leftTxStr = t.getSource().getValue().toString();
            // 填充到:rootLayout的leftSource
            this.fillRootLayoutLeftContent(leftTxStr, ResourceType.FILE);
        });
        service.setOnFailed((WorkerStateEvent t)-> {
            System.out.println("[RFLS]load json path:"+remoteForm.getFilePath()+", happed fail:(:");
            this.fillRootLayoutLeftContent(null, ResourceType.FILE);
        });
        service.start();
    }
    private void fillRootLayoutLeftContent(String content, ResourceType type) {
        System.out.println("[RFLS][0]start fill Json Result");
        if(null == content || content.isEmpty()){
            System.out.println("[RFLS][1]fill Json Result Argument::fail::");
            this.failLoadStatus();
            return;
        }
        // --------------------------------------------------------->
        System.out.println("[RFLS][2]finish fill Json Result, current loaded before status:"+this.isSuccess().get());
        // 更新加载是否结束
        this.finishLoadStatus();
        System.out.println("[RFLS][3]loaded after status:"+this.isSuccess().get());
        // --------------------------------------------------------->
        Platform.runLater(()->{
            // 当数据量很大时会很卡@20230328-1
            // 向主控制器传递值@2
            JsonResult result = JsonResult.getInstance();
            // 统一进到jsonResult@20230329
            result.setResult(content);
            result.setResource(type.getNames());
        });
    }

    public boolean isLoaded() {
        return loaded.get();
    }

    public SimpleBooleanProperty loadedProperty() {
        return loaded;
    }

    public boolean isSuccessed() {
        return successed.get();
    }

    public SimpleBooleanProperty successedProperty() {
        return successed;
    }

    /**
     * 是否成功了
     * @return
     */
    public BooleanBinding isSuccess(){
        return this.loaded.and(this.successed);
    }

    public EventStream<Change<Boolean>> stream(){
        System.out.println("[RFLS]fire event stream start:::"+isSuccess().get());
        return EventStreams.changesOf(isSuccess());
    }

}
